import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 86136
 * Date: 2025-05-04
 * Time: 10:10
 */
public class UdpEchoServer {
    private DatagramSocket socket = null;

    public UdpEchoServer(int port) throws SocketException {
        socket = new DatagramSocket(port);
    }
    public void start() throws IOException {
        System.out.println("启动服务器");
        while(true) {
            //循环一次相当于处理一次请求，分为三个步骤
            //1.读取请求并解析
            //DatagramPacket表示一个数据报，此处传入的字节数组就是保存的udp的载荷
            DatagramPacket requestSocket = new DatagramPacket(new byte[4096],4096);
            socket.receive(requestSocket);//receive -> IOException
            //将读取到的二进制数据转化为字符串，只构造有效部分
            String request = new String(requestSocket.getData(),0,requestSocket.getLength());

            //2.根据请求计算响应
            String response = process(request);

            //3.把响应返回给客户端
            //构造用于发送长度的分组的数据报包 length指定主机上到指定的端口号。
            //getBytes() 使用平台的默认字符集将此 String编码为字节序列，将结果存储到新的字节数组中。
            //此处的长度不能直接使用response.length()，因为这是获取字符个数，而实际应该获取字节个数
            DatagramPacket responseSocket = new DatagramPacket(response.getBytes(),response.getBytes().length,requestSocket.getSocketAddress());
            //此时还不能直接发送，因为udp协议自身没有保存对方方信息，所以要制定目的IP和目的端口
            socket.send(responseSocket);//从此套接字发送数据报包,不会阻塞

            //4.打印--记录这一次客户端和服务端交互的过程
            System.out.printf("[%s:%d] req:%s reps:%s\n",requestSocket.getAddress().toString(),requestSocket.getPort(),request,response);
        }
    }

    //private方法不能被重写，后续要写别的服务器就只需修改这里，可以通过重写方法
    public String process(String request) {
        return request;
    }

    public static void main(String[] args) throws IOException {
        UdpEchoServer server = new UdpEchoServer(9090);
        server.start();
    }
}
